import time
from tkinter.ttk import Progressbar

import hid
import tkinter as tk  # 导入tkinter模块。为了方便后续讲解，命名为 tk。
import tkinter.messagebox  # 引入弹窗库，防止解释器弹出报错。
from tkinter import Tk, Button, filedialog, messagebox

root = tk.Tk()
author = tk.Label(root, text="作者：诚意微嵌")
mailbox = tk.Label(root, text="邮箱：786659185g@qq.com")
textbox = tk.Text(root, height=10, width=30)
send_cnt: int = 0


def find_device(vid, pid):
    while True:
        # 查找设备

        devices = hid.enumerate(vid, pid)
        # if not devices:
        # raise ValueError('设备未找到')
        if devices:
            textbox.delete('1.0', 'end')
            textbox.insert("insert", "找到指定设备\n")
            root.update()
            print("找到指定设备")
            break
        else:
            textbox.delete('1.0', 'end')
            textbox.insert("insert", "未找到指定设备，等待重试...\n")
            print("未找到指定设备，等待重试...")
            root.update()
            time.sleep(1)  # 等待5秒后重试
    # tk.messagebox.showerror(title='无法打开设备',
    #                         message='设备未找到')  # 消息提醒弹窗，点击确定返回值为 ok

    # 获取第一个设备的路径
    device_path = devices[0]['path']
    # 使用路径创建设备实例
    usb_devices = hid.device()
    usb_devices.open_path(device_path)
    # 打开设备
    # if not usb_devices.open_path(device_path):
    #     raise IOError("无法打开设备")
    return usb_devices


def send_firmware(device, firmware_path):
    global send_cnt
    with open(firmware_path, 'rb') as f:
        firmware = f.read()
    # 将固件分成64字节的数据包
    packets = [firmware[i:i + 64] for i in range(0, len(firmware), 64)]

    #
    # device.write(b'Wait to upgrade')
    #
    while True:
        data = "".join(map(chr, device.read(64)))
        print(data)
        if data and data.find("Wait to upgrade") != -1:
            device.write(b" Start upgrading")
            break
    while True:
        data = "".join(map(chr, device.read(64)))
        print(data)
        if data and data.find("ok") != -1:
            device.write(b" " + len(packets).to_bytes(4, byteorder='little'))
            print("固件包数量：", len(packets))
            break
    # 发送数据包
    for packet in packets:
        while True:
            data = "".join(map(chr, device.read(64)))
            print(data)
            if data:
                if data.find("ok") != -1:
                    print((b'\0' + packet)[2:])
                    device.write(b'\0' + packet)
                    send_cnt = send_cnt + 1
                    textbox.delete('1.0', 'end')
                    # textbox.insert("insert", "升级进度: " + str(100 / len(packets) * send_cnt, 2) + "%\n")
                    textbox.insert("insert", "升级进度: " + str(round(100 / len(packets) * send_cnt, 2)) + "%\n")

                    root.update()
                    print("已发送数据包数量：", send_cnt)
                    break


def choose_file():
    file_path = filedialog.askopenfilename(filetypes=[('Binary Files', '*.bin')])
    if file_path:
        try:
            device = find_device(0x483, 0x0)
            textbox.delete('1.0', 'end')
            textbox.insert("insert", "设备已找到，开始固件升级\n")
            root.update()
            print("设备已找到，开始固件升级")
            send_firmware(device, file_path)
            textbox.delete('1.0', 'end')
            textbox.insert("insert", "固件升级成功\n")
            tk.messagebox.showinfo(title='升级成功', message="固件升级成功")
        except Exception as e:
            tk.messagebox.showerror(title='错误',
                                    message={e})  # 消息提醒弹窗，点击确定返回值为 ok


def main():
    # root = Tk()
    Button(root, text="选择固件文件", command=choose_file).pack(pady=20)
    textbox.pack()
    author.pack()
    mailbox.pack()
    root.title("固件升级程序")
    root.geometry("300x300")

    textbox.pack()
    textbox.insert("insert", "请选择固件后在插入设备！！！\n")
    root.mainloop()


if __name__ == "__main__":
    main()
